

#include "ReconstructionUserObject.h"
#include "libmesh/string_to_enum.h"


registerMooseObject("O4App", ReconstructionUserObject);

template <>
InputParameters
validParams<ReconstructionUserObject>()
{
  InputParameters params = validParams<GeneralUserObject>();
  MooseEnum orders("CONSTANT FIRST SECOND THIRD FOURTH", "FIRST");
  params.addParam<MooseEnum>("order",
                             orders,
                             "指定重构变量的精度");

  MooseEnum families("MONOMIAL L2_HIERARCHIC L2_LAGRANGE XYZ", "MONOMIAL");                            
  params.addParam<MooseEnum>("family",
                              families,
                              "有限元类型"
                            );                            

  MooseEnum solver_types("CG CGN CGS CR QMR TCQMR TFQMR BICG BICGSTAB MINRES GMRES LSQR  JACOBI  SOR_FORWARD SOR_BACKWARD SSOR  RICHARDSON CHEBYSHEV SPARSELU INVALID_SOLVER", "GMRES");
  params.addParam<MooseEnum>("solver_type", 
                              solver_types,
                              "求解重构矩阵的方法");
  MooseEnum preconditioner_types("IDENTITY_PRECOND JACOBI_PRECOND BLOCK_JACOBI_PRECOND SOR_PRECOND SSOR_PRECOND EISENSTAT_PRECOND ASM_PRECOND CHOLESKY_PRECOND ICC_PRECOND ILU_PRECOND LU_PRECOND USER_PRECOND SHELL_PRECOND AMG_PRECOND INVALID_PRECONDITIONER", "BLOCK_JACOBI_PRECOND");
  params.addParam<MooseEnum>("preconditioner_type", 
                              preconditioner_types,
                              "预处理矩阵类型");                                                         
  return params;
}

ReconstructionUserObject::ReconstructionUserObject(const InputParameters & parameters)
  : GeneralUserObject(parameters),
  _rs_sys(std::make_shared<ReconstructionSystem>(_fe_problem, "rs0"))
{
    auto order = Utility::string_to_enum<Order>(getParam<MooseEnum>("order"));
    auto family = Utility::string_to_enum<FEFamily>(getParam<MooseEnum>("family"));
    _rs_sys->setOrder(order);
    _rs_sys->setFEType({order, family});

    auto solver_type = Utility::string_to_enum<SolverType>(getParam<MooseEnum>("solver_type"));
    _rs_sys->setSolverType(solver_type);

    auto preconditioner_type = Utility::string_to_enum<PreconditionerType>(getParam<MooseEnum>("preconditioner_type"));
    _rs_sys->setPreconditionerType(preconditioner_type);

    _rs_sys->init();
}

// ReconstructionUserObject::ReconstructionUserObject(ReconstructionUserObject & x, Threads::split /*split*/)
//   : GeneralUserObject(x.parameters()),
//     BlockRestrictable(&x),
//     Coupleable(this, false),
//     MooseVariableDependencyInterface(),
//     _mesh(x._subproblem.mesh()),
//     _current_elem(x._assembly.elem()),
//     _current_elem_volume(x._assembly.elemVolume()),
//     _q_point(x._assembly.qPoints()),
//     _qrule(x._assembly.qRule()),
//     _JxW(x._assembly.JxW()),
//     _coord(x._assembly.coordTransformation()),
//     _have_interface_elems(false)
// {
//   // Keep track of which variables are coupled so we know what we depend on
//   const std::vector<MooseVariableFEBase *> & coupled_vars = x.getCoupledMooseVars();
//   for (unsigned int i = 0; i < coupled_vars.size(); i++)
//     addMooseVariableDependency(coupled_vars[i]);
// }

ReconstructionUserObject::~ReconstructionUserObject() {}

void
ReconstructionUserObject::initialize()
{
}


void
ReconstructionUserObject::execute()
{
  _console << " ReconstructionUserObject::execute" << std::endl;
  _rs_sys->solve();
}

void
ReconstructionUserObject::finalize()
{
}

